package com.sanshengshui.netty.oioAndnio;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

/**
 * @author zyl
 * @description
 * @since 2024/7/17
 */
public class NettyNioServer {
    public void server(int port) throws Exception {
        //1.创建要发送的消息缓冲区
        //这里创建了一个缓冲区（ByteBuf），其中包含了要发送的消息 "Hi!\r\n"，使用 UTF-8 编码
        final ByteBuf buf = Unpooled.copiedBuffer("Hi!\r\n",
                Charset.forName("UTF-8"));
        //2.创建事件循环组
        //创建一个事件循环组（EventLoopGroup），用于处理所有的事件。NioEventLoopGroup 是一个基于非阻塞 I/O 的实现
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            //3.配置服务器
            //创建 ServerBootstrap 实例
            //ServerBootstrap 是一个帮助类，用于设置服务器
            ServerBootstrap b = new ServerBootstrap();
            //设置事件循环组 将前面创建的事件循环组（group）设置为服务器的事件处理组
            //设置通道类型 指定通道类型为 NioServerSocketChannel，这是一个基于非阻塞 I/O 实现的服务器通道
            b.group(group).channel(NioServerSocketChannel.class)
                    //设置本地地址 将服务器绑定到指定的端口
                    .localAddress(new InetSocketAddress(port))
                    //设置子处理器
                    //设置子处理器，ChannelInitializer 用于帮助用户配置新创建的 Channel。
                    // 在 initChannel 方法中，向通道的流水线（pipeline）添加了一个 ChannelInboundHandlerAdapter 实例。
                    // channelActive 方法在通道激活时被调用，向客户端写入并刷新消息，然后关闭连接
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch)
                                throws Exception{
                            ch.pipeline().addLast(
                                    new ChannelInboundHandlerAdapter() {
                                        @Override
                                        public void channelActive(
                                                ChannelHandlerContext ctx) throws Exception {
                                            ctx.writeAndFlush(buf.duplicate())
                                                    .addListener(
                                                            ChannelFutureListener.CLOSE);
                                        }
                                    });
                        }
                    });
            //绑定服务器并开始接受连接
            //调用 bind() 方法绑定服务器，并调用 sync() 方法等待绑定完成。然后，等待服务器通道的关闭事件
            ChannelFuture f = b.bind().sync();
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }

}
